﻿using Grow.Domain.Repository;

namespace Grow.Domain.Object
{
    /// <summary>
    /// 值对象
    /// 参考地址：https://docs.microsoft.com/zh-cn/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/implement-value-objects
    /// </summary>
    /// <typeparam name="TValueObject">值对象类型</typeparam>
    public abstract class ValueObjectBase : IDomainObject
    {
        protected static bool EqualOperator(ValueObjectBase? left, ValueObjectBase? right)
        {
            return !(left is null ^ right is null) && (left is null || left.Equals(right));
        }

        protected static bool NotEqualOperator(ValueObjectBase? left, ValueObjectBase? right)
        {
            return !EqualOperator(left, right);
        }

        protected abstract IEnumerable<object> GetEqualityComponents();

        public override bool Equals(object? obj)
        {
            if (obj == null || obj.GetType() != GetType())
            {
                return false;
            }

            ValueObjectBase other = (ValueObjectBase)obj;

            return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
        }

        public override int GetHashCode()
        {
            return GetEqualityComponents()
                .Select(x => x != null ? x.GetHashCode() : 0)
                .Aggregate((x, y) => x ^ y);
        }

        public ValueObjectBase? GetCopy()
        {
            return MemberwiseClone() as ValueObjectBase;
        }
    }
}
